package com.lin.gameserver.protobuf;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.lin.proto.RequestMsg;
import com.lin.proto.ResponseMsg;
import com.lin.proto.*;

import java.util.HashMap;
import java.util.Map;

/**
 * Protobuf消息包装器，用于封装请求和响应消息
 */
public class MessageWrapper {
    
    // 请求信息
    private RequestMsg requestMsg;
    
    // 响应信息
    private ResponseMsg.Builder responseBuilder;
    
    /**
     * 构造请求消息包装器
     *
     * @param requestBytes 请求二进制数据
     * @throws InvalidProtocolBufferException 解析失败时抛出异常
     */
    public MessageWrapper(byte[] requestBytes) throws InvalidProtocolBufferException {
        this.requestMsg = RequestMsg.parseFrom(requestBytes);
        this.responseBuilder = ResponseMsg.newBuilder()
                .setCmd(CommandId.toResponseCmd(requestMsg.getCmd()))
                .setSeq(requestMsg.getSeq())
                .setErrorCode(com.lin.proto.ErrorCode.ErrorNone);
    }
    
    /**
     * 获取请求命令号
     *
     * @return 命令号
     */
    public int getCmd() {
        return requestMsg.getCmd();
    }
    
    /**
     * 获取请求序列号
     *
     * @return 序列号
     */
    public long getSeq() {
        return requestMsg.getSeq();
    }
    
    /**
     * 获取请求消息体
     *
     * @return 请求消息体字节数组
     */
    public byte[] getRequestBody() {
        return requestMsg.getBody().toByteArray();
    }
    
    /**
     * 解析请求消息体
     *
     * @param parser 消息解析器
     * @param <T> 消息类型
     * @return 解析后的消息对象
     * @throws InvalidProtocolBufferException 解析失败时抛出异常
     */
    public <T extends Message> T parseRequestBody(com.google.protobuf.Parser<T> parser) throws InvalidProtocolBufferException {
        return parser.parseFrom(requestMsg.getBody());
    }
    
    /**
     * 设置响应消息体
     *
     * @param message 响应消息
     * @return this
     */
    public MessageWrapper setResponseBody(Message message) {
        responseBuilder.setBody(ByteString.copyFrom(message.toByteArray()));
        return this;
    }
    
    /**
     * 设置错误码
     *
     * @param errorCode 错误码
     * @return this
     */
    public MessageWrapper setErrorCode(int errorCode) {
        responseBuilder.setErrorCode(com.lin.proto.ErrorCode.forNumber(errorCode));
        return this;
    }
    
    /**
     * 添加选项
     *
     * @param key 选项键
     * @param value 选项值
     * @return this
     */
    public MessageWrapper addOption(int key, String value) {
        Map<Integer, String> opts = new HashMap<>(responseBuilder.getOptMap());
        opts.put(key, value);
        responseBuilder.putAllOpt(opts);
        return this;
    }
    
    /**
     * 获取响应消息的二进制数据
     *
     * @return 二进制数据
     */
    public byte[] getResponseBytes() {
        return responseBuilder.build().toByteArray();
    }
    
    /**
     * 创建一个空响应（通常用于错误情况）
     *
     * @param cmd 命令号
     * @param seq 序列号
     * @param errorCode 错误码
     * @return 二进制响应数据
     */
    public static byte[] createEmptyResponse(int cmd, long seq, int errorCode) {
        ResponseMsg response = ResponseMsg.newBuilder()
                .setCmd(CommandId.toResponseCmd(cmd))
                .setSeq(seq)
                .setErrorCode(com.lin.proto.ErrorCode.forNumber(errorCode))
                .build();
        return response.toByteArray();
    }
    
    /**
     * 创建一个服务器推送消息
     *
     * @param cmd 命令号
     * @param message 消息体
     * @return 二进制数据
     */
    public static byte[] createNotifyMessage(int cmd, Message message) {
        ResponseMsg response = ResponseMsg.newBuilder()
                .setCmd(cmd)
                .setSeq(0)
                .setErrorCode(com.lin.proto.ErrorCode.ErrorNone)
                .setBody(ByteString.copyFrom(message.toByteArray()))
                .build();
        return response.toByteArray();
    }
} 